//
//  Console.m
//  c_Render
//
//  Created by liao peterson on 11/9/09.
//  Copyright 2009 uestc. All rights reserved.
//

#import "Console.h"



@implementation Console
@synthesize renderScene;
@synthesize startp;
@synthesize endp;
@synthesize flag;
@synthesize flag1;

-(GLuint)LoadShader:(GLenum)type:(const char*)ShaderSrc
{
	GLuint shader;
	GLint compile;
	
	shader=glCreateShader(type);
	if(shader==0)
	{
#ifdef DEBUG_MODE
		printf("Creating Shader Failed At Graphics.c LoadShader\n");
#endif		
		return 0;
	}
	glShaderSource(shader, 1, &ShaderSrc,NULL);
	glCompileShader(shader);
#ifdef DEBUG_MODE
	glGetShaderiv(shader, GL_COMPILE_STATUS, &compile);
	if(!compile)
	{
		GLint infoLen=0;
		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
		if(infoLen>1)
		{
			char*infoLog=(char*)malloc(sizeof(char)*infoLen);
			glGetShaderInfoLog(shader, infoLen, NULL, infoLog);
			NSLog(@"%x LOAD SHADER FAILED %s",type,infoLog);
			free(infoLog);
		}
		glDeleteShader(shader);
		return 0;
	}
#endif
	NSLog(@"%x LOAD SHADER SUCCESSFULLY",type);
	return shader;
}

-(void)InitRenderTarget:(const Scene*)scene
{
	GLint num=renderScene->mList->count;
	RenderModelTargets = (RenderModel**)malloc(num * sizeof(RenderModel*));
	for(int i=0;i<num;i++)
	{
		renderScene->mList->SetCurrent(i);
		renderScene->phySim->fList->SetCurrent(i);
		RenderModelTargets[i] = new RenderModel(renderScene->mList->current->data,renderScene->phySim->fList->current->data);
	}
	font = new RenderTexture("font.png");
	UI = new RenderTexture("UI.png");
}

-(void)Graphics_Init:(const GLchar*)sceneName :(CALayer*)cal
{
	layer = cal;
	fbManager = [[FrameBufferManager alloc] init];
	[fbManager initEAGL:layer];
	
	flag=0;
	renderScene=new Scene;
	renderScene->LoadScene(sceneName);
	nmeshes=new Meshes;
	
	GLuint	shaderObject[2];
	GLuint	programObject;
	
	shaderObject[0]=[self LoadShader:GL_VERTEX_SHADER:vertexShaderSrc];
	shaderObject[1]=[self LoadShader:GL_FRAGMENT_SHADER:fragmentShaderSrc];
	
	programObject=glCreateProgram();
	glAttachShader(programObject, shaderObject[0]);
	glAttachShader(programObject, shaderObject[1]);
	
	//glDeleteBuffers(num, vboIds);
	
	glBindAttribLocation(programObject, 0, "a_color");
	glBindAttribLocation(programObject, 1, "a_position");
	glBindAttribLocation(programObject, 2, "a_normal");
	glBindAttribLocation(programObject, 3, "a_lamploc");
	glBindAttribLocation(programObject, 4, "a_texCoord");
	glBindAttribLocation(programObject, 5, "a_lamprgb");
	glBindAttribLocation(programObject, 6, "a_camloc");
	glBindAttribLocation(programObject, 7, "drawMode");
	
	glVertexAttrib3fv(3,renderScene->lList->tail->data->loc);
	glVertexAttrib3fv(5,renderScene->lList->tail->data->rgb);
	
	
	//glFrontFace(GL_CW);
	glEnable(GL_CULL_FACE);
	//glDisable(GL_CULL_FACE);
	glClearColor(1.0f,1.0f,1.0f,1.0f);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glEnable(GL_TEXTURE_2D);
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
	glBlendEquation(GL_FUNC_ADD);
	
	glLinkProgram(programObject);
	m_u_mvpHandle=glGetUniformLocation(programObject, "u_mvpMatrix");
	tex_Handle=glGetUniformLocation(programObject, "s_texture");
	m2w_Handle=glGetUniformLocation(programObject, "Model2World");
	glUseProgram(programObject);
	
	glEnableVertexAttribArray(1);
	glEnableVertexAttribArray(2);
	glEnableVertexAttribArray(4);
	
	t=0;
	
	//m_u_mvpHandle,m2w_Handle;
	//RenderObject::m_u_mvpHandle = m_u_mvpHandle;
	//RenderObject::m2w_Handle = m2w_Handle;
	[self InitRenderTarget:renderScene];
}

-(void)Graphics_Draw
{
	if(flag)
	{
		renderScene->cList->current->data->loc.x+=renderScene->cList->current->data->look.x*0.1;
		renderScene->cList->current->data->loc.y+=renderScene->cList->current->data->look.y*0.1;
	}
	vec3 vTemp;
	vTemp.setValue(0.0f,0.0f,1.0f);
	renderScene->cList->current->data->rotateAroundAxis(vTemp,camSpeedX);
	renderScene->cList->current->data->dir.z -= camSpeedX;
	vec3 v1;
	v1.setValue(renderScene->cList->current->data->loc.x,renderScene->cList->current->data->loc.y,0);
	vTemp = renderScene->cList->current->data->loc % v1;
	GLfloat r = renderScene->cList->current->data->dir.x - camSpeedY;
	if(r>0&&r<1.3)
	{
		renderScene->cList->current->data->rotateAroundAxis(vTemp,camSpeedY);
		renderScene->cList->current->data->dir.x -= camSpeedY;
	}
	camSpeedX *= 0.95;
	camSpeedY *= 0.95;
	renderScene->cList->current->data->SetMatrix();
	glVertexAttrib3fv(6,(GLfloat*)&renderScene->cList->tail->data->loc);
	
	if(flag1)
	{
		vec3 pt = {startp.x, startp.y, 0};
		GLint index;
		if((index=renderScene->updateFinger(pt))!=-1)
		{
			for(int i=index;i<renderScene->mList->count;i++)
				RenderModelTargets[i]=RenderModelTargets[i+1];
		}
		flag1 = 0;
	}
	renderScene->phySim->update();
	
	// Actual Rendering starts here....
	[fbManager bindMainFrameBuffer];
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
	Camera*cam=renderScene->cList->current->data;
	for(int i=0;i<renderScene->mList->count;i++)
	{
		RenderModelTargets[i]->render(cam->World2Camera,m2w_Handle,m_u_mvpHandle);
	}
	
	UI->render(-1.0f, -1.0f, 1.0f, -0.5f);
	GLint time[3];
	time[0]=(t/60)%10;
	time[1]=(t/600)%10;
	time[2]=(t/6000)%10;
	font->RenderNumber(0.2f, -0.95f, time[2], 1.0f);
	font->RenderNumber(0.41f, -0.95f, time[1], 1.0f);
	font->RenderNumber(0.62f, -0.95f, time[0], 1.0f);
	
	[fbManager renderMainFrameBuffer];
	t++;
}

-(void)Graphics_Quit
{
	delete ortho,
	delete rot;
	delete transform;
	
	delete textureIds;
	
	for(int i=0;i<renderScene->mList->count;i++)
		delete RenderModelTargets[i];
	
	delete RenderModelTargets;
	
	delete renderScene;
	delete nmeshes;
}

-(void) touchBegin
{
	//flag=0;
}

-(void) touchEnded
{
	//flag=0;
}

-(void)touchMoved
{
	//renderScene->cList->current->data->dir[2]-=(endp.x-startp.x)/100;
	//renderScene->cList->current->data->dir[0]-=(endp.y-startp.y)/100;
	//renderScene->cList->current->data->updateQuat((startp.x - endp.x)/100, (endp.y - startp.y)/100, 0);
	//renderScene->cList->current->data->updateQuat(-(endp.y - startp.y)/100, -(endp.x - startp.x)/100, 0);
	camSpeedX += (endp.x - startp.x)/1000.0f;
	camSpeedY += (endp.y - startp.y)/1000.0f;
	startp.x = endp.x;
	startp.y = endp.y;
}

@end
